﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace JobShop
{
    [Description("Represents the solution in a form of binary chromosome")]
    public class TcChromosome : TiDuplicable<TcChromosome>
    {
        private readonly Int32 M;
        private readonly Int32 N;
        private readonly TcProblem Problem;
        public Int32 Length { get; private set; }
        public Boolean[] Genotype { get; set; }
        //------------------------------------------------------------------------------

        public TcChromosome(TcProblem prmProblem)
        {
            M = prmProblem.M;
            N = prmProblem.N;
            Problem = prmProblem;
            Length = M * N * (N - 1);
            Genotype = new Boolean[Length];

            // Create the random genotype.
            CreateRandomGenotype();
        }
        //------------------------------------------------------------------------------

        [Description("This function creates the random genotype")]
        private void CreateRandomGenotype()
        {
            Random seed = new Random();
            for (Int32 j = 0; j < Length; j++)
                Genotype[j] = seed.Next() % 2 == 1;
        }
        //------------------------------------------------------------------------------

        [Description("Modify the given bit of chromosome and update the phenotype")]
        public void Modify(Int32 prmRow, Int32 prmCol, Int32 prmMachine)
        {	
            if (prmRow != prmCol)
            {
                Int32 n;
                Int32 val = 1;
                
                if (prmRow > prmCol)
                {
                    n = prmRow;
                    prmRow = prmCol;
                    prmCol = n;
                    val = 0;
                }
                n = N - 1;
                Int32 m = (n - 1) - prmRow;
                Int32 index = n * (n + 1) / 2 - m * (m + 1) / 2 - (N - prmCol);
                index = Convert.ToInt32(index * M + Problem.TaskOrder[prmRow, prmMachine]);
                Genotype[index] = val == 1;
            }
        }
        //------------------------------------------------------------------------------

        [Description("Build a chromosome from a phenotype")]
        public void Build(TcPhenotype prmPhenotype)
        {
            for (int m = 0; m < M; m++)
                for (int x = 0; x < (N - 1); x++)
                    for (int y = (x + 1); y < N; y++)
			            Modify(prmPhenotype.Solution[m, x], prmPhenotype.Solution[m, y], m);
        }
        //------------------------------------------------------------------------------

        [Description("Replace the bits within the given range and returns the existing ones")]
        public Boolean[] ReplaceBits(Int32 prmBegin, Int32 prmEnd, Boolean[] prmData)
        {
            Int32 count = prmEnd - prmBegin + 1;
            if (prmEnd >= 0 && prmEnd < Genotype.Length && prmBegin >= 0 && prmBegin <= prmEnd && prmData.Length == count)
            {
                Boolean[] existing = new Boolean[count];
                Array.Copy(Genotype, prmBegin, existing, 0, count);
                Array.Copy(prmData, 0, Genotype, prmBegin, count);
                return existing;
            }
            return prmData;
        }
        //------------------------------------------------------------------------------

        [Description("Flips one specific bit in the chromosome")]
        public Boolean FlipBit(Int32 prmBit)
        {
            if (prmBit < 0 || prmBit > Length - 1)
                return false;

            Genotype[prmBit] = !Genotype[prmBit];
            return true;
        }
        //------------------------------------------------------------------------------

        [Description("Flips one specific bit in the chromosome")]
        public Boolean FlipBits(Int32[] prmBits)
        {
            Boolean result = true;
            for (int i = 0; i < prmBits.Length; i++)
                result = result && FlipBit(prmBits[i]);
            return result;
        }
        //------------------------------------------------------------------------------

        public Boolean[] GetBits(Int32 prmBegin, Int32 prmEnd)
        {
            Int32 count = prmEnd - prmBegin + 1;
            if (prmEnd >= 0 && prmEnd < Genotype.Length && prmBegin >= 0 && prmBegin <= prmEnd && count > 0)
            {
                Boolean[] existing = new Boolean[count];
                Array.Copy(Genotype, prmBegin, existing, 0, count);
                return existing;
            }
            return null;
        }
        //------------------------------------------------------------------------------

        public TcChromosome Duplicate()
        {
            return Clone() as TcChromosome;
        }
        //------------------------------------------------------------------------------

        public object Clone()
        {
            TcChromosome clone = new TcChromosome(Problem);
            clone.Length = Length;
            Array.Copy(Genotype, clone.Genotype, Length);
            return clone;
        }
        //------------------------------------------------------------------------------

    }
    //------------------------------------------------------------------------------

}
//------------------------------------------------------------------------------
